﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
using MediaRss.Formatter;

using Xunit;

namespace MediaRss.Tests
{
	public class MediaRssSerializationTests
	{

		#region helper methods

		private static MediaRssItem GetFirstItemFromFeed()
		{
			MediaRssFeed feed = LoadFeed();
			return feed.Items.AsMediaRssItems().First();
		}

		private static MediaRssFeed LoadFeed()
		{
			var reader = XmlReader.Create("SampleMedia.rss");
			var feed = SyndicationFeed.Load<MediaRssFeed>(reader);

			Assert.NotNull(feed);
			Assert.Equal("Song Site", feed.Title.Text);
			Assert.Equal("Media RSS example with new fields added in v1.5.0", feed.Description.Text);
			Assert.True(feed.Items.Count() > 0);

			return feed;
		}
		#endregion

		#region Community Node
		[Fact]
		public void CommunityNodeNotNull()
		{
			MediaRssItem firstItem = GetFirstItemFromFeed();

			Assert.NotNull(firstItem.CommunityNode);
			Assert.NotNull(firstItem.CommunityNode.Rating);
			Assert.NotNull(firstItem.CommunityNode.Stats);
			Assert.NotNull(firstItem.CommunityNode.TagItems);

			Assert.Equal(3.5, firstItem.CommunityNode.Rating.Average);
		}

		[Fact]
		public void CommunityNodeStarRating()
		{
			StarRating rating = GetFirstItemFromFeed().CommunityNode.Rating;
			Assert.NotNull(rating);

			Assert.Equal(3.5, rating.Average);
			Assert.Equal(20, rating.Count);
			Assert.Equal(1, rating.Min);
			Assert.Equal(10, rating.Max);
		}

		[Fact]
		public void CommunityNodeStatistics()
		{
			Statistics stats = GetFirstItemFromFeed().CommunityNode.Stats;
			Assert.NotNull(stats);

			Assert.Equal(5, stats.Views);
			Assert.Equal(5, stats.Favorites);
		}

		[Fact]
		public void CommunityNodeTags()
		{
			Tags tags = GetFirstItemFromFeed().CommunityNode.TagItems;
			Assert.NotNull(tags);

			Assert.NotNull(tags.TagCollection);
			Assert.Equal(2, tags.TagCollection.Count());

			KeyValuePair<string, int> newsItem = tags.TagCollection.ElementAt(0);

			Assert.Equal("news", newsItem.Key);
			Assert.Equal(5, newsItem.Value);

			KeyValuePair<string, int> abcItem = tags.TagCollection.ElementAt(1);

			Assert.Equal("abc", abcItem.Key);
			Assert.Equal(3, abcItem.Value);
		}
		#endregion

		#region Comments Node
		[Fact]
		public void CommentsNodeNotNull()
		{
			Comments comments = GetFirstItemFromFeed().CommentsNode;

			Assert.NotNull(comments);
			Assert.NotNull(comments.CommentItems);
		}

		[Fact]
		public void CommentsItems()
		{
			Comments comments = GetFirstItemFromFeed().CommentsNode;
			
			Assert.Equal(2, comments.CommentItems.Count());

			Comment firstComment = comments.CommentItems.ElementAt(0);
			
			Assert.Equal("comment1", firstComment.CommentText);
			
			Comment secondComment = comments.CommentItems.ElementAt(1);
			Assert.Equal("comment2", secondComment.CommentText);
		}
		
		#endregion

		#region Embed Node
		[Fact]
		public void EmbedNodeNotNull()
		{
			Embed embed  = GetFirstItemFromFeed().EmbedNode;

			Assert.NotNull(embed);
			Assert.NotNull(embed.ParameterItems);
		}

		[Fact]
		public void EmbedAttributes()
		{
			Embed embed = GetFirstItemFromFeed().EmbedNode;

			Assert.Equal(@"http://www.foo.com/player.swf", embed.Url.AbsoluteUri);

			Assert.Equal(512, embed.Width);
			Assert.Equal(323, embed.Height);
		}

		[Fact]
		public void EmbedParameterCollection()
		{
			Collection<Parameter> parameterItems = GetFirstItemFromFeed().EmbedNode.ParameterItems;
			Assert.Equal(5, parameterItems.Count());

			Parameter typeParam = parameterItems.ElementAt(0);
			Assert.Equal("type", typeParam.Name);
			Assert.Equal("application/x-shockwave-flash", typeParam.Content);

			Parameter widthParam = parameterItems.ElementAt(1);
			Assert.Equal("width", widthParam.Name);
			Assert.Equal("512", widthParam.Content);
			
			Parameter heightParam = parameterItems.ElementAt(2);
			Assert.Equal("height", heightParam.Name);
			Assert.Equal("323", heightParam.Content);
			
			Parameter allowFullScreenParam = parameterItems.ElementAt(3);
			Assert.Equal("allowFullScreen", allowFullScreenParam.Name);
			Assert.Equal("true", allowFullScreenParam.Content);
			
			Parameter flashVarsParam = parameterItems.ElementAt(4);
			Assert.Equal("flashVars", flashVarsParam.Name);
			Assert.Equal(@"id=12345&vid=678912i&lang=en-us&intl=us&thumbUrl=http://www.foo.com/thumbnail.jpg", flashVarsParam.Content);
		}
		#endregion

		[Fact]
		public void SerializeInMemory()
		{
			var reader = XmlReader.Create("SampleMedia.rss");
			var formatter = new MediaRssFeedFormatter(new MediaRssFeed());
			formatter.ReadFrom(reader);

			var settings = new XmlWriterSettings
			{
				NewLineOnAttributes = true,
				NamespaceHandling = NamespaceHandling.OmitDuplicates,
				CloseOutput = true,
				Indent = true
			};

			var writer = XmlWriter.Create("TestOutput.rss", settings);
			formatter.WriteTo(writer);

			Debug.WriteLine(writer.ToString());
			writer.Close();
		}

		[Fact]
		public void CreateNewRSSFile()
		{
			MediaRssFeed myFeed = new MediaRssFeed();
			
			myFeed.Copyright = new TextSyndicationContent("Copyright 2010-2020 @ Because it looks good");
			myFeed.Description = new TextSyndicationContent("This is a sample media feed");
			myFeed.Title = new TextSyndicationContent("Hello Media Feed World!");

			var feedItems = new List<MediaRssItem>();

			var item = new MediaRssItem();
			var rating = new StarRating {Min = 1, Max = 5};
			item.CommunityNode.Rating = rating;

			feedItems.Add(item);

			myFeed.Items = feedItems;


			var settings = new XmlWriterSettings
			{
				NewLineOnAttributes = true,
				NamespaceHandling = NamespaceHandling.OmitDuplicates,
				CloseOutput = true,
				Indent = true
			};

			using (var writer = XmlWriter.Create("TestOutput.rss", settings))
			{
				var formatter = new MediaRssFeedFormatter(myFeed);
				formatter.WriteTo(writer);
			}
		}

	}
}
